package com.gym.code.generator;

import static com.gym.code.generator.Contants.$import;
import static com.gym.code.generator.Contants.$lineSplit;
import static com.gym.code.generator.Contants.$tab;
import static com.gym.code.generator.utils.GenerateFileUtils.generateChar;
import static com.gym.code.generator.utils.GenerateFileUtils.generateWithSpace;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.StringUtils;

import com.gym.code.generator.EnumContants.AccessModifierType;
import com.gym.code.generator.EnumContants.FieldClassType;
import com.gym.code.generator.model.mapping.BaseGenerateModel;
import com.gym.code.generator.model.mapping.bean.BeanGenerateModel;
import com.gym.code.generator.model.mapping.bean.EnumGenerateModel;
import com.gym.code.generator.model.mapping.field.EnumFieldGenerateModel;
import com.gym.code.generator.model.mapping.field.FieldGenerateModel;
import com.gym.code.generator.model.mapping.field.ParameterFieldGenerateModel;
import com.gym.code.generator.model.mapping.field.ParameterListValueFieldGenerateModel;
import com.gym.core.date.DateContants.DateFormatType;
import com.gym.core.date.DateFormatUtils;

/**
 * 
 * @author xinchun.wang 
   @email: 532002108@qq.com
 * @createTime 2015-5-23 下午6:38:55 
 * @param <T>
 */
public abstract class AbstractContentGenerator<T extends BaseGenerateModel> implements Generator<List<String>, T> {
	
	public final List<String> generate(T bean) {
		return generateContent(bean);
	}

	private final List<String> generateContent(T bean) {
		List<String> result = new ArrayList<String>();
		result.add(generatePackage(bean));
		result.addAll(generateImport(bean));
		result.addAll(generateClassNote(bean));
		result.addAll(doGenerateClassContent(bean));
		return result;
	}
	
	/**
	 * 生成类的注释
	 */
	protected  List<String> generateClassNote(T bean){
		return Arrays.asList(generateNoteBegin()," * @author "+bean.getCreater(),
				" * @createTime " + DateFormatUtils.parseDate(new Date(), DateFormatType.YYYY_MM_DD_HH_MM_SS)
				,generateNoteEnd());
	}
	
	/**
	 * 生成package行信息
	 */
	protected abstract  String generatePackage(T bean);
	
	
	/**
	 * 生成import行信息
	 */
	protected final String generateImportLine(String pack){
		return $import +" " + pack +$lineSplit;
	}
	
	
	protected final String generatePropertyLine(AccessModifierType modifyType,String propertyClassName,String properyName){
		return generatePropertyLine(modifyType,propertyClassName,properyName,null);
	}
	
	protected final String generatePropertyLine(AccessModifierType modifyType,String propertyClassName,String properyName,String defaultValue) {
		if(StringUtils.isEmpty(defaultValue)){
			return generateWithSpace(Arrays.asList(generateChar(1,$tab),modifyType.getName(),propertyClassName,properyName+$lineSplit));
		}
		return generateWithSpace(Arrays.asList(generateChar(1,$tab),modifyType.getName(),propertyClassName,properyName," = " + defaultValue+$lineSplit));
	}
	
	
	private final  List<String> generateImport(T bean){
		Set<String> importSet = doGenerateImport(bean);
		List<String> result = new ArrayList<String>();
		for(String item : importSet){
			result.add(generateImportLine(item));
		}
		return result;
	}
	
	
	protected final String generateNoteBegin(){
		return "/**";
	}
	
	protected final String generateNoteEnd(){
		return "*/";
	}
	
	protected abstract Set<String> doGenerateImport(T bean); 
	
	protected  List<String> doGenerateClassContent(T bean){
		List<String> result = new ArrayList<String>();
		result.addAll(generateClassBegin(bean));
		result.addAll(generateFields(bean));
		result.addAll(generateInitMethods(bean));
		result.addAll(generateMethods(bean));
		result.addAll(generateOthers(bean));
		result.add(generateClassEnd());
		return result;
	}
	
	protected abstract List<String> generateClassBegin(T bean);

	protected abstract List<String> generateFields(T bean);

	/**
	 * 生成方法信息
	 */
	protected abstract List<String> generateMethods(T bean);
	
	protected  List<String> generateInitMethods(T bean) {
		return Collections.emptyList();
	}

	
	final private  String generateClassEnd(){
		return "}";
	}
	
	
	protected  List<String> generateOthers(T bean){
		return Collections.emptyList();
	}
	
	protected final Set<String> generateParameterImport(List<ParameterFieldGenerateModel> params,BeanGenerateModel beanGenerateModel) {
		List<FieldGenerateModel> result = new ArrayList<FieldGenerateModel>();
		for(ParameterFieldGenerateModel item : params){
			result.add(item);
		}
		return generateFieldImport(result,beanGenerateModel);
	}
	
	protected  Set<String> generateFieldImport(List<FieldGenerateModel> params,BeanGenerateModel beanGenerateModel){
		Set<String> result = new HashSet<String>();
		
		for(FieldGenerateModel item : params){
			if(item instanceof EnumFieldGenerateModel) {
				EnumGenerateModel enumGenerateModel = ((EnumFieldGenerateModel)item).getEnumGenerateModel();
				if(enumGenerateModel != null){
					result.add(enumGenerateModel.getPackageName() +"."+beanGenerateModel.getBeanNameByFirstLetterUpper()+"."+enumGenerateModel.getEnumTypeNameByFirstLetterUpper());
				}
			}else if(item instanceof ParameterListValueFieldGenerateModel){
				result.add("java.util.List");
			}if(item instanceof ParameterFieldGenerateModel) {
				EnumGenerateModel enumGenerateModel = ((ParameterFieldGenerateModel)item).getEnumGenerateModel();
				if(enumGenerateModel != null){
					result.add(enumGenerateModel.getPackageName() +"."+beanGenerateModel.getBeanNameByFirstLetterUpper()+"."+enumGenerateModel.getEnumTypeNameByFirstLetterUpper());
				}
			} 
			
			if(FieldClassType.date == item.getValueType() || FieldClassType.datetime == item.getValueType()){
				result.add("java.util.Date");
			}
		}
		return result;
	
	}
}
